<?php
declare (strict_types=1);

namespace app\admin\controller;

use app\BaseController;
use think\exception\ValidateException;
use think\response\Json;
use app\common\model\MaterialLibrary;

class Uploads extends BaseController
{
    //错误信息
    public $error;

    //允许上传格式
    protected string $fileExt = 'jpg,png,gif,jpeg';

    //上传大小限制
    protected string $filesize = '5242880';

    protected string $regular = "/(3c25.*?28.*?29.*?253e)|(3c3f.*?28.*?29.*?3f3e)|(3C534352495054)|(2F5343524950543E)|(3C736372697074)|(2F7363726970743E)/is";

    public function uploadImage(): Json
    {
        $file = request()->file();

        try {

            $this->validate($file, ['file' => 'filesize:' . $this->filesize . '|fileExt:' . $this->fileExt . '']);

            $url = $this->app->config->get('filesystem.disks.public.url') . date('Ymd');

            $path = $this->app->config->get('filesystem.disks.public.root') . date('Ymd');

            $res = explode('.', $file['file']->getOriginalName());
            $name = $res[0] . md5(date('YmdHis')) . '.' . $res[1];

            $result = $file['file']->move($path, $name);

            $image = $url . '/' . $result->getFileName();

            if (!$this->illegalCheck($image)) return json(['code' => -1, 'msg' => $this->error]);

            return json(['code' => 200, 'msg' => '上传成功', 'data' => ['url' => $image, 'name' => $result->getFileName()]]);

        } catch (\Exception $e) {

            return json(['code' => -1, 'msg' => '上传失败:' . $e->getMessage()]);
        }
    }

    public function uploadEditorVideo(): Json
    {
        $file = request()->file();

        try {
            $this->validate($file, ['file' => 'filesize:52428800|fileExt:mp4']);
            $url = $this->app->config->get('filesystem.disks.public.url') . date('Ymd');
            $name = $file['wangeditor-uploaded-video']->getOriginalName();
            $path = $this->app->config->get('filesystem.disks.public.root') . date('Ymd');
            $result = $file['wangeditor-uploaded-video']->move($path, $name);
            $image = $url . '/' . $result->getFileName();
            if (!$this->illegalCheck($image)) return json(['code' => -1, 'msg' => $this->error]);
            return json(['errno' => 0, 'data' => ['url' => $image, 'alt' => $file['wangeditor-uploaded-video']->getOriginalName()]]);
        } catch (\Exception $e) {
            return json(['errno' => 1, 'message' => '上传失败:' . $e->getMessage()]);
        }
    }

    /**
     * @param $disks -- 文件路径
     * @return bool
     * 验证图片是否含有非法文件
     */
    private function illegalCheck($disks): bool
    {
        $file = '.' . $disks;

        if (file_exists($file)) {
            $resource = fopen($file, 'rb');
            $fileSize = filesize($file);
            fseek($resource, 0);

            if ($fileSize > 512) {
                $hexCode = bin2hex(fread($resource, 512));
                fseek($resource, $fileSize - 512);
                $hexCode .= bin2hex(fread($resource, 512));
            } else { // 取全部
                $hexCode = bin2hex(fread($resource, $fileSize));
            }
            fclose($resource);

            $check = preg_match('#__HALT_COMPILER()#i', $hexCode)
                || preg_match('#/script>#i', $hexCode)
                || preg_match('#<([^?]*)\?php#i', $hexCode)
                || preg_match('#<\?\=#i', $hexCode);
            if ($check) {
                $this->error = '非法文件上传！';
                $this->remove($file);
                return false;
            }

            $result = preg_match($this->regular, $hexCode);

            if ($result) {
                $this->error = '非法文件上传！';
                $this->remove($file);
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }
    }

    /**
     * @param $disks -- 文件路径
     * @return bool
     * 删除文件
     */
    private function remove($file): bool
    {
        if (file_exists($file)) {
            unlink($file);
            return true;
        } else {
            return false;
        }
    }


}